<?php

/**
 * 威海综保仓SDK
 * @author chenyun
 */
namespace App\Service\VendorClient\Shopweihai;
use App\Service\Code\Normal;
use App\Service\TaskServer\TaskWorker;
use Service\AppService\IdService;
use Hyperf\Utils\WaitGroup;

class ShopweihaiApiClient
{
    private $account  = 'Shopweihai';
    protected $config;
    protected $RouteMap = [
        'getAccessToken'        => 'Member.Account.Login',
        'createOrder'           => 'Trade.Order.CreateSupplierOrder',
        'cancelOrder'           => 'Trade.Order.OrderCancel',
        'queryGoodsList'        => 'Product.Item.ItemInventory',
    ];

    protected $goods_type = [
        0 => 'Trade.Order.CreateGeneralTradeOrder',
        1 => 'Trade.Order.CreateSupplierOrder',
    ];
    /**
     * 初始参数
     * @param obj $collection
     */
    public function __construct( $apiBody = [] ) 
    {
        $this->config = $apiBody;
    }
    
    /**
     * 创建订单
     */
    public function createOrder( $params = [] ) 
    {   
        ini_set('serialize_precision', 16);
        if( empty($params['supplierOrder']) || empty($params['orderGoods']) || empty($params['order']) || empty($params['binfo']) ) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder or orderGoods or order or binfo");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        $order     = $params['order'];
        $apply_extends    = [];
        //运费
        $deliver_money  = $orderInfo['deliver_money'];
        //商品类型
        $goodsType  = 0;
        //商品下单组
        $skuList    = [];
        $productAmt = 0;
        $TaxAmt     = 0;
        foreach ($params['orderGoods'] as $key => $item ) 
        {
            //卖价
            $price              = $item['price'];
            //商品购买规格数量
            $spec_num           = $item['spec_num'];
            //商品购买数量(下单数量 X 起售数量)
            $quantity           = $item['quantity'];
            //实际购买数量
            $buyAcount          = $spec_num * $quantity ;
            //如果商品除不尽，得多取以为，减去实际金额为折扣，折扣不能为负数
            if( $key == 0 ) {
                $singleDeliveryMoney = bcdiv((string)$deliver_money,(string)$quantity,3);
                $singleDeliveryMoney = bcmul((string)$singleDeliveryMoney,(string)100,1);
                $singleDeliveryMoney = bcdiv((string)ceil($singleDeliveryMoney), (string)100,2);
                $price               = bcadd((string)$price, (string)$singleDeliveryMoney,2);
            }
            //单个商品价格
            $singleGoodsPrice   = bcdiv((string)$price, (string)$spec_num,3);
            $singleGoodsPrice   = ceil(bcmul((string)$singleGoodsPrice,(string)'100',1));
            $singleGoodsPrice   = bcdiv((string)$singleGoodsPrice,'100',2);
            $totalGoods         = bcmul((string)$singleGoodsPrice,(string)$buyAcount,2);

            //含税税率
            $tax_rate           = bcadd('1', (string)$item['tax_rate'],4);
            //不含税价格
            $not_tax_price      = bcdiv((string)$singleGoodsPrice, (string)$tax_rate,3);
            // echo "含税税率:".$tax_rate."不含税价格：".$not_tax_price;
            $not_tax_price      = ceil(bcmul((string)$not_tax_price,(string)'100',1));
            // echo "含税税率:".$tax_rate."不含税价格：".$not_tax_price;
            $not_tax_price      = bcdiv((string)$not_tax_price,'100',2);
            
            //税金
            $singleGoodsTax     = bcsub((string)$singleGoodsPrice, (string)$not_tax_price,3);
            
            //单个商品总税金
            $totalGoodsTax  = bcmul((string)$singleGoodsTax,(string)$buyAcount,2);
            
            //单个商品总不含税价格
            $totalGoods     = bcmul((string)$not_tax_price,(string)$buyAcount,2);
            //商品组
            $skuList[] = [
                "commodityCode"     => $item['supplier_skucode'],
                "commodityName"     => $item['goods_name'],
                "qty"               => $buyAcount,
                "price"             => $not_tax_price,
                "amount"            => $totalGoods,
            ];
            $productAmt = bcadd((string)$productAmt,(string)$totalGoods,2);
            $TaxAmt = bcadd((string)$TaxAmt,(string)$totalGoodsTax,2);
        }
        
        $goodsType = $params['orderGoods'][0]["goods_type"];
        //实际下单金额
        $real_total_money = $orderInfo['real_total_money'];
        //订单总金额 = 含税商品总金额 + 运费 - 优惠金额
        $ActualPaidAmt = bcadd((string)$productAmt,(string)$TaxAmt,2);
        //优惠金额
        $discount_money = bcsub((string)$ActualPaidAmt,$real_total_money,2);
        
        //下单支付的时候支付信息
        $apply_extends  = @json_decode($orderInfo['apply_extends'],true);
        //支付时间
        $payTime        = empty($order['payTime']) ? $orderInfo['pay_time'] :$order['payTime'];
        //支付时间
        $pay_time       = $payTime ? $payTime : time();
        $orderDate      = $pay_time - (5 * 60);
        $pay_time       = date('Y-m-d H:i:s',$pay_time);
        $orderDate      = date('Y-m-d H:i:s',$orderDate);
        //支付流水号
        $pay_sn             = $order['paySerial'] ?? $orderInfo['pay_sn'];

        //获取上游供应商支付方式路由
        $payCommanyCode = $apply_extends['payCommanyCode'] ?? '';
        $PayCompanyCode = $order['payCommanyCode'] ? $order['payCommanyCode'] : $payCommanyCode;

        //电商平台信息
        $enterpriseNum  = $apply_extends['enterpriseNum'] ?? '';
        $enterpriseNum  = $order['enterpriseNum'] ? $order['enterpriseNum'] : $enterpriseNum;

        //获取token信息
        $access_token = $this->getAccessToken();
        if($access_token["code"] != Normal::SUC){
            return $access_token;
        }
        //创建订单数据
        $data = [
            'orderSource'       => 0,
            'orderCode'         => $orderInfo['supplier_dsn'],
            'companyCode'       => '',
            'receiverName'      => $orderInfo['receive_name'],
            'mobile'            => $orderInfo['recveive_phone'],
            'province'          => $orderInfo['province'],
            'city'              => $orderInfo['city'],
            'district'          => $orderInfo['district'],
            'receiverAddress'   => $orderInfo['receive_address'],
            'receiverZip'       => '',
            'payCompanyType'    => 0,
            'payNumber'         => $pay_sn,
            'payDate'           => $pay_time,
            'expressCode'       => '',
            'expressNo'         => '',
            'payment'           => $real_total_money,
            'couponAmount'      => $discount_money,
            'orderTotalAmount'  => $ActualPaidAmt,
            'orderGoodsAmount'  => $ActualPaidAmt,
            'orderTaxAmount'    => $TaxAmt,
            'feeAmount'         => 0,
            'insureAmount'      => 0,
            'paperType'         => '01',
            'name'              => $orderInfo['buyer_realname'],
            'paperNumber'       => $orderInfo['buyer_idcard'],
            'holdCode'          => '',
            'recept'            => true,
            'receptUrl'         => $this->config["notify_url"],
            'orderDate'         => $orderDate,
            'memberId'          => 0,
            'clientId'          => 0,
            'ordertype'         => 0,
            'outOrderCode'      => $orderInfo['supplier_dsn'],
            'commodityCodeType' => 1,
            'eplatformCode'     => $enterpriseNum,
            'payCompanyCode'    => $PayCompanyCode,
            'shopid'            => '',
            'OrderDtls'         => $skuList,
        ];
        $orders =  json_encode(['Orders' => [$data]],JSON_UNESCAPED_UNICODE);
        $requestParam = [
            'method'    => 'createOrder',
            'data'      => [
                'appkey'        => $this->config["appkey"],
                'code'          => $this->goods_type[$goodsType],
                'data'          => $orders,
                'sign'          => $this->getSign($orders),
                'access_token'  => $access_token["data"],
            ]
        ];
        $res = $this->execute($requestParam);
        if( $res["code"]==Normal::SUC ){
            $result = current($res["data"]);
            if($result[0]["resultCode"] != "true"){
                return Normal::returnCode(Normal::FAIL,"推单失败：".json_encode($res["data"],JSON_UNESCAPED_UNICODE));
            }
        }
        return $res;
    }
   
    /**
     * 获取取消订单
     */
    public function cancelOrder( $params = [] ) 
    {
        $orderSupplier= $params['supplierOrder'];
        $access_token = $this->getAccessToken();
        if($access_token["code"] != Normal::SUC){
            return $access_token;
        }
        $data = [
            'out_order_code'   => $orderSupplier['supplier_dsn'],
            'cancel_memo'      => $params["order"]["exceptReason"],
        ];
        $orders =  json_encode(['Orders' => [$data]],JSON_UNESCAPED_UNICODE);
        $requestParam = [
            'method'    => 'cancelOrder',
            'data'      => [
                'appkey'    => $this->config["appkey"],
                'code'      => $this->RouteMap['cancelOrder'],
                'data'      => $orders,
                'sign'      => $this->getSign($orders),
                'access_token'  => $access_token["data"],
            ]
        ];
        $res = $this->execute($requestParam);
        if( $res["code"]==Normal::SUC ){
            $result = current($res["data"]["data"]);
            if($result["result"] != true){
                return Normal::returnCode(Normal::FAIL,"取消失败：".json_encode($res["data"],JSON_UNESCAPED_UNICODE));
            }
        }
        return $res;
        
    }
    /**
     * 查询商品详情
     */
    public function queryGoodsList($param)
    {
        //获取token
        $access_token = $this->getAccessToken();
        if($access_token["code"] != Normal::SUC){
            return Normal::returnCode(Normal::FAIL,"获取token失败，请核对仓库配置参数！",[
                'has_next'  => false,
                'total'     => 0,
                'list'      => []
            ]);
        }
        $this->token = $access_token["data"];
        $details = [];
        $count = count($param["skuNos"]);
        $wg = new WaitGroup();
        $wg->add($count);
        foreach ($param["skuNos"] as $sku){
            co(function () use ($wg,$sku,& $details) {
                $where = [
                    'bar_code'   => $sku,
                    'page_index' => 1,
                    'page_size'  => 5,
                ];
                $data = json_encode($where,JSON_UNESCAPED_UNICODE);
                $requestParam = [
                    'method'    => 'queryGoodsList',
                    'data'      => [
                        'appkey'    => $this->config["appkey"],
                        'code'      => $this->RouteMap['queryGoodsList'],
                        'data'      => $data,
                        'sign'      => $this->getSign($data),
                        'access_token'  => $this->token,
                    ]
                ];
                $responseData = $this->execute($requestParam);
                if ($responseData['code'] == Normal::SUC && isset($responseData["data"]) && !empty($responseData['data']) && !empty($responseData['data']["skus"])){
                    $skus = current($responseData['data']["skus"]);
                    $details[] = $skus;
                }
                $wg->done();
            });
        }
        $wg->wait();
        return Normal::returnCode(Normal::SUC,"获取成功",[
            'has_next'  => true,
            'total' => count($details),
            'list'  => $details
        ]);
    }
    
    /**
     * 查询token值
     * @param array $param
     */
    public function getAccessToken()
    {
        $data = [
            'member_code'   => $this->config["member_code"],
            'password'      => $this->config["password"],
        ];
        $requestParam = [
            'method'    => 'getAccessToken',
            'data'      => [
                'appkey'    => $this->config["appkey"],
                'code'      => $this->RouteMap['getAccessToken'],
                'data'      => json_encode($data,JSON_UNESCAPED_UNICODE),
                'sign'      => $this->getSign(json_encode($data,JSON_UNESCAPED_UNICODE)),
            ]
        ];
        $res =  $this->execute($requestParam);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        $token = $res["data"]["token"];
        return Normal::returnCode(Normal::SUC,"获取成功",$token);
    }
    
    /**
     * 加签
     * @param array $param
     */
    protected function getSign( string  $params )
    {
        $string = $params.$this->config["secret"];
        return md5($string);
    }
    
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function execute( $param = [] )  
    {
        if( empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }
        $method = $param["method"];
        $url    = $this->config["baseurl"];
        $parameter = [
            [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $url,
                'data'      => $param['data'],
                'method'    => 'post',
                'format'    => 'form-data',
                'header'    => [],
        
            ],
        ];
        if( in_array($method,['getAccessToken','queryGoodsList']) ) {
            $resTask = TaskWorker::instance()->addTask($parameter,'handleDiableTask');
        } else {
            $resTask = TaskWorker::instance()->addTask($parameter);
        }
        $resTask = current($resTask);
        $res     = $resTask['response']['result'];
        $resHttp = json_decode($res,true);
        if( isset($resHttp['ResultCode']) && $resHttp['ResultCode'] == '00' ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$resHttp["ResultData"]);
        }
        $message = isset($resHttp['ResultMsg']) ? $resHttp['ResultMsg'] : '请求失败';
        return Normal::returnCode(Normal::FAIL,$message);
    }
}